package com.ihr360.binlog.component;


import com.alibaba.fastjson.JSONObject;
import com.alibaba.otter.canal.protocol.CanalEntry;
import com.google.common.collect.Lists;
import com.ihr360.binlog.dto.BinLogReceivedEvent;
import com.ihr360.binlog.model.EventRow;
import com.ihr360.binlog.service.BinLogReceiveEventService;
import com.ihr360.commons.lang.CollectionUtils;
import com.ihr360.commons.lang.DateUtils;
import com.ihr360.commons.lang.StringUtils;
import com.ihr360.commons.model.type.BinLogEventStatus;
import com.ihr360.entity.SyncedRosterSalaryChangeRecordEntity;
import com.ihr360.type.StaffStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import rx.functions.Action1;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 订阅tab_roster_salary_change_record 数据变化
 */
@Component
public class RosterSalayrChangeRecordEventEmitter {
    Logger logger = LoggerFactory.getLogger(RosterSalayrChangeRecordEventEmitter.class.getName());

    private static final List<String> support_change = Lists.newArrayList("试用期转正","调岗调薪");

    @Autowired
    private BinLogReceiveEventService binLogReceiveEventService;

    @Value("${ihr360.tab_roster_salary_change_record.sync.by.lastupdate:false}")
    private boolean syncIfLastUpdateChanged;

    public Action1<EventRow> onEventRow = new Action1<EventRow>() {
        @Override
        public void call(EventRow syncRow) {
            CanalEntry.RowChange rowChange = syncRow.getRowChange();
            for (CanalEntry.RowData rowData : rowChange.getRowDatasList()) {
                CanalEntry.EventType eventType = rowChange.getEventType();
                if (eventType == CanalEntry.EventType.INSERT) {
                    List<CanalEntry.Column> canalColumns = rowData.getAfterColumnsList();
                    updateChanges2Dest(canalColumns);
                    continue;
                } else if (eventType == CanalEntry.EventType.UPDATE) {
                    List<CanalEntry.Column> canalColumns = rowData.getAfterColumnsList();
                    updateChanges2Dest(canalColumns);
                }
            }
        }
    };

    private void updateChanges2Dest(List<CanalEntry.Column> canalColumns) {
        if (CollectionUtils.isEmpty(canalColumns)) {
            return;
        }

        Map<String, CanalEntry.Column> columnMap = canalColumns.stream().collect(Collectors.toMap(CanalEntry.Column::getName, c -> c));

        CanalEntry.Column companyIdCol = columnMap.get(SyncedRosterSalaryChangeRecordEntity.Field.companyId);
        CanalEntry.Column staffIdCol = columnMap.get(SyncedRosterSalaryChangeRecordEntity.Field.staffId);
        CanalEntry.Column userIdCol = columnMap.get(SyncedRosterSalaryChangeRecordEntity.Field.userId);
        CanalEntry.Column userNameCol = columnMap.get(SyncedRosterSalaryChangeRecordEntity.Field.userName);
        CanalEntry.Column changeReasonCol = columnMap.get(SyncedRosterSalaryChangeRecordEntity.Field.changeReason);
        CanalEntry.Column changeContentCol = columnMap.get(SyncedRosterSalaryChangeRecordEntity.Field.changeContent);
        CanalEntry.Column changeDateCol = columnMap.get(SyncedRosterSalaryChangeRecordEntity.Field.changeDate);

        String changeReason = getValue(changeReasonCol);
        if (!support_change.contains(changeReason)) {
            return;
        }

        boolean isUpdate = isUpdate(companyIdCol)
                || isUpdate(staffIdCol)
                || isUpdate(userIdCol)
                || isUpdate(userNameCol)
                || isUpdate(changeReasonCol)
                || isUpdate(changeContentCol)
                || isUpdate(changeDateCol);

        if (!isUpdate && !syncIfLastUpdateChanged) {
            return;
        }
        SyncedRosterSalaryChangeRecordEntity entity = new SyncedRosterSalaryChangeRecordEntity();
        entity.setCompanyId(getValue(companyIdCol));
        entity.setStaffId(getValue(staffIdCol));
        entity.setUserId(getValue(userIdCol));
        entity.setUserName(getValue(userNameCol));
        entity.setChangeReason(getValue(changeReasonCol));
        entity.setChangeContent(getValue(changeContentCol));
        entity.setChangeDate(getDate(changeDateCol));
        BinLogReceivedEvent event = new BinLogReceivedEvent();
        event.setCreatedAt(new Date());
        event.setUpdatedAt(new Date());
        event.setStatus(BinLogEventStatus.PENDING);
        event.setContent(JSONObject.toJSONString(entity));
        binLogReceiveEventService.save(event);

    }

    private String getValue(CanalEntry.Column column) {
        return column != null ? column.getValue() : null;
    }

    private Date getDate(CanalEntry.Column column) {
        return column != null && StringUtils.isNotEmpty(column.getValue()) ? DateUtils.dateFormat(column.getValue(), DateUtils.STANDARD_DATE_FORMAT_YMD) : null;
    }

    private boolean getBool(CanalEntry.Column column) {
        return column != null ? Boolean.valueOf(column.getValue()) : false;
    }

    private boolean isUpdate(CanalEntry.Column column) {
        return column != null ? column.getUpdated() : false;
    }

    private Long getLongValue(CanalEntry.Column column) {
        return column != null ? (StringUtils.isNotEmpty(column.getValue()) ? Long.valueOf(column.getValue()) : null) : null;
    }

    private StaffStatus getStaffStatus(CanalEntry.Column column) {
        return column != null ? StaffStatus.valueOf(column.getValue()) : null;
    }


}
